package controllers

import (
	"crypto/md5"
	"errors"
	"fmt"
	"github.com/astaxie/beego"
	"go/types"
	"go_upload_file/models"
	_ "go_upload_file/models/utils"
	util "go_upload_file/models/utils"
	"io"
	"math/rand"
	"mime/multipart"
	"net/http"
	"os"
	"path"
	"time"
)

type FileUploadController struct {
	BaseController
}

type FileUploadInfo struct {
	Id           int    `json:"id"`
	Filename     int    `json:"filename"`     // 当前是第几片
	Hash         int    `json:"hash"`         // 每片的大小
	Path         string `json:"path"`         // 当前分片的大小
	CategoryCode string `json:"categoryCode"` // 文件的总大小
	Status       int    `json:"status"`       // 总分片数
}

func (this *FileUploadController) UploadFile() {
	resultInfo := util.JSONS{}
	msg, err := this.Upload()
	// 错误返回
	if err != nil {
		resultInfo.Error(msg)
		this.Data["json"] = resultInfo
		this.ServeJSON()
		return
	}
	// 成功返回
	resultInfo.Success("文件上传成功！", types.Interface{})
	this.Data["json"] = resultInfo
	this.ServeJSON()
	return
}

// 校验文件
func (c FileUploadController) fileValidate(file *multipart.FileHeader) (msg string, err error) {
	ext := path.Ext(file.Filename)
	var AllowExtMap map[string]bool = map[string]bool{
		".jpg": true, ".jpeg": true, ".png": true,
		".JPG": true, ".JPEG": true, ".PNG": true,
	}
	if _, ok := AllowExtMap[ext]; !ok {
		msg = "图片后缀不符合上传要求"
		return msg, errors.New(msg)
	}
	maxSize, _ := beego.AppConfig.Int64("upload.multipart.max-file-size")
	if file.Size > maxSize {
		msg = "文件大小超过限制"
		return msg, errors.New(msg)
	}
	return "", nil
}

func (this *FileUploadController) Upload() (msg string, err error) {
	files, _ := this.GetFiles("files")         //获取上传的文件
	categoryCode := this.GetString("category") //获取上传的文件
	fmt.Printf("categoryCode: [%s] ", categoryCode)
	msg, err = "", nil
	method := this.Ctx.Request.Method
	if method != "POST" {
		return "请求方式不正确", nil
	}
	var fileSize int64 = 0
	maxRequestSzie, _ := beego.AppConfig.Int64("upload.multipart.max-request-size")
	for i, _ := range files {
		//for each fileheader, get a handle to the actual file
		var file multipart.File
		filename := files[i].Filename
		originalFilename := filename
		ext := path.Ext(filename)
		file, err := files[i].Open()
		defer file.Close()
		msg, err := this.fileValidate(files[i])
		if err != nil {
			return msg, err
		}
		fileSize += fileSize + files[i].Size
		if fileSize > maxRequestSzie {
			msg = "文件内容超过最大上传限制"
			return msg, err
		}
		var w http.ResponseWriter

		//构造文件名称
		rand.Seed(time.Now().UnixNano())
		randNum := fmt.Sprintf("%d", rand.Intn(9999)+1000)
		hashName := md5.Sum([]byte(time.Now().Format("2006_01_02_15_04_05_") + randNum))
		fileName := fmt.Sprintf("%x", hashName) + ext
		//this.Ctx.WriteString(  fileName )

		fileDir := time.Now().Format("20060102") + "/"
		uploadDir := beego.AppConfig.String("upload.path") + fileDir
		uploadPath := uploadDir + fileName
		filePath := beego.AppConfig.String("upload.prefix") + "/" + fileDir + fileName
		err = os.MkdirAll(uploadDir, 777)
		if err != nil {
			this.Ctx.WriteString(fmt.Sprintf("%v", err))
			msg = "目录创建失败"
			return msg, err
		}
		//create destination file making sure the path is writeable.
		dst, err := os.Create(uploadPath)
		defer dst.Close()
		if err != nil {
			msg = "文件创建失败"
			return msg, err
		}
		//copy the uploaded file to the destination file
		if _, err := io.Copy(dst, file); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			msg = "文件拷贝失败"
			return msg, err
		}
		// 保存到数据库
		fileupload := &models.FileUpload{
			Filename:     originalFilename,
			Path:         filePath,
			CategoryCode: categoryCode,
			Status:       0,
			UploadTime:   time.Now(),
		}
		count, err := fileupload.InsertOneRecord()
		if count < 1 {
			msg = "数据插入失败:" + err.Error()
			return msg, err
		}
	}
	return msg, err
}

// 根据文件类别获取图片列表
func (this *FileUploadController) GetPictureList() {
	pageSize, _ := this.GetInt("pageSize")
	pageNum, _ := this.GetInt("pageNum")
	categoryCode := this.GetString("categoryCode")
	resultInfo := util.JSONS{}
	method := this.Ctx.Request.Method
	if method != "GET" {
		resultInfo.Error("请求方式不正确")
		this.Data["json"] = resultInfo
		this.ServeJSON()
		return
	}
	// 函数调用
	var list []models.FileUpload
	list, err := models.NewFileUpload().GetList(pageSize, pageNum, categoryCode)
	if err != nil {
		return
	}
	//rows := [len(list)]*util.Row{}
	rows := make([]util.Row, len(list))
	for i, l := range list {
		rows[i].Id = l.Id
		rows[i].FileName = l.Filename
		rows[i].Src = l.Path
		rows[i].Category = l.CategoryCode
	}
	// 错误返回
	if err != nil {
		resultInfo.Error(err.Error())
		this.Data["json"] = resultInfo
		this.ServeJSON()
		return
	} else {
		resultInfo.Success("返回成功", rows)
		this.Data["json"] = resultInfo
		this.ServeJSON()
		return
	}
}

// 获取文件类别
func (this *FileUploadController) GetFileCategory() {
	method := this.Ctx.Request.Method
	resultInfo := util.JSONS{}
	if method != "GET" {
		resultInfo.Error("请求方式不正确")
		this.Data["json"] = resultInfo
		this.ServeJSON()
		return
	}
	var res []models.FileCategory
	res, err := models.NewFileCategory().GetList()
	if err != nil {
		resultInfo.Error("返回失败：" + err.Error())
		this.Data["json"] = resultInfo
		this.ServeJSON()
		return
	} else {
		resultInfo.Success("返回成功", res)
		this.Data["json"] = resultInfo
		this.ServeJSON()
		return
	}
}
